use std::collections::HashMap;
use std::boxed::Box;
use std::path::PathBuf;
use std::path::Path;
use std::env;
use sdl2::rect::Rect;
use sdl2::render::WindowCanvas;
use sdl2::{Sdl, VideoSubsystem};
use sdl2::video::WindowContext;
use sdl2::render::TextureCreator;
use sdl2::pixels::Color;
use rand::Rng;
use find_folder::Search;
use crate::tetris::*;
use crate::events::*;
use crate::gfx::*;
use crate::constant::*;


events!{
    keyboard: {
        key_escape: Escape,
        key_up: Up,
        key_down: Down,
        key_left: Left,
        key_right: Right,
        key_space: Space,
        key_n: N,
        key_r: R,
        key_p: P
    }
}

pub struct App {
    pub events: Events,
    pub tetris: Tetris,
    pub canvas: WindowCanvas,
    pub ttf_context: ::sdl2::ttf::Sdl2TtfContext,
    pub font_path: PathBuf,
    pub elapsed: f64,
}

impl App{
    pub fn new(events: Events, tetris: Tetris, canvas: WindowCanvas, ttf_context: ::sdl2::ttf::Sdl2TtfContext) -> App {
        let mut exe_folder = env::current_exe().unwrap();
        exe_folder.pop();//去掉执行文件名
        let mut path_buf: PathBuf = Search::Parents(3).of(exe_folder).for_folder(ASSETS).expect("not found path");
        path_buf.push(FONT_NAME);
        App {
            events: events,
            tetris: tetris,
            ttf_context: ttf_context,
            font_path: path_buf,
            canvas: canvas,
            elapsed: 0f64,
        }
    }


    pub fn ttf_str_sprite<'a>(&self, creator: &'a TextureCreator<WindowContext>, text: &str, point_size: u16, color: Color) -> Option<Sprite<'a>> {
        let font = self.ttf_context.load_font(self.font_path.as_path(), point_size).unwrap();
        font.render(text)
            .blended(color)
            .ok()
            .and_then(|surface| creator.create_texture_from_surface(&surface).ok())
            .map(Sprite::new)
    }
}

pub enum ViewAction {
    None,
    Quit,
    ChangeView(Box<View>),
}

pub trait View {
    fn render(&mut self, context: &mut App, elapsed: f64) -> ViewAction;
}

pub fn spwan<F>(titile: &str, init: F) where F: Fn(&mut App) -> Box<View> {
    // Initialize SDL2
    let sdl_context: Sdl = ::sdl2::init().unwrap();
    let video: VideoSubsystem = sdl_context.video().unwrap();
    let mut timer = sdl_context.timer().unwrap();
    let ttf_context = ::sdl2::ttf::init().unwrap();

    // Create the window
    let window = video.window(titile, WIDTH, HEIGHT)
        .position_centered()
        .opengl()
        //.resizable()
        .build()
        .unwrap();

    let mut canvas: WindowCanvas = window.into_canvas().build().unwrap();
    //let texture_creator = canvas.texture_creator();

    let mut game = App::new(
        Events::new(sdl_context.event_pump().unwrap()),
        Tetris::new(),
        canvas,
        ttf_context
    );

    let mut current_view = init(&mut game);

    let interval = 1_000 / 60;//间隔 60帧，每帧多长时间？
    let mut before = timer.ticks();
    let mut last_second = timer.ticks();
    let mut fps = 0u16;
    loop {

        let now = timer.ticks();
        let dt = now - before;

        if dt < interval {
            timer.delay(interval - dt);
            continue;
        }

        before = now;
        fps += 1;
        if now - last_second > 1_000 {
            //println!("FPS: {}", fps);
            last_second = now;
            fps = 0;
        }
        let elapsed = dt as f64 / 1_000.0;
        game.events.pump();

        match current_view.render(&mut game, elapsed) {
            ViewAction::None => game.canvas.present(),
            ViewAction::Quit => { break },
            ViewAction::ChangeView(new_view) => {
                current_view = new_view;
            }
        }
    }
}

